package com.zkyt.lib_msdk_ext.component

import com.geoai.mavlink.geoainet.obstacle.enums.ObstacleAvoidanceType
import com.geoai.mavlink.geoainet.obstacle.enums.ObstacleCameraSource
import com.geoai.mavlink.geoainet.obstacle.info.ObstacleStateInfo
import com.geoai.mavlink.geoainet.obstacle.interfaces.IObstacleManager
import com.zkyt.lib_msdk_ext.common.CallbackWithRxHandler
import com.zkyt.lib_msdk_ext.common.SDKExtUtil
import io.reactivex.Completable
import io.reactivex.Observable
import io.reactivex.Single
import io.reactivex.subjects.BehaviorSubject
import java.util.Optional

/**
 * Created by chenyu on 2024/1/10
 * Description:
 */
object ObstacleManagerExt: AbsSDKExt<IObstacleManager>(), IRemovableComp {
    private val isConnectSubject = BehaviorSubject.createDefault(false)
    private var obstacleManager: IObstacleManager? = null

    private var originObstacleStateSubject =
        BehaviorSubject.createDefault(Optional.empty<ObstacleStateInfo>())

    override fun init(originManager: IObstacleManager) {
        obstacleManager = originManager

        obstacleManager?.setObstacleDataListener { obstacleStateInfo ->
            originObstacleStateSubject.onNext(Optional.of(obstacleStateInfo))
        }
        isConnectSubject.onNext(true)
    }

    override fun destroy() {
        super.destroy()
        isConnectSubject.onNext(false)
        obstacleManager?.setObstacleDataListener(null)
        originObstacleStateSubject.onNext(Optional.ofNullable(null))

        obstacleManager = null
    }

    override fun isConnected(): Boolean {
        return isConnectSubject.value!!
    }

    override fun getConnectedObservable(): Observable<Boolean> {
        return isConnectSubject.hide()
    }

    override fun getOriginManager(): IObstacleManager? {
        return obstacleManager
    }

    fun getObstacleStateInfoObservable(): Observable<Optional<ObstacleStateInfo>> {
        return originObstacleStateSubject.hide()
    }

    fun setObstacleAvoidanceTypeRx(type: ObstacleAvoidanceType): Completable {
        return Completable.create { emitter ->
            obstacleManager?.setObstacleAvoidanceType(type) {
                SDKExtUtil.handleError(emitter, it)
            }
        }
    }

    fun getObstacleAvoidanceTypeRx(): Single<ObstacleAvoidanceType> {
        return Single.create { emitter ->
            obstacleManager?.getObstacleAvoidanceType(CallbackWithRxHandler(emitter))
        }
    }

    fun getObstacleAvoidanceTypeObservable(): Observable<Optional<ObstacleAvoidanceType>> {
        val curMethod = object : Any() {}.javaClass.enclosingMethod
        return autoGetProcessor.getAutoGetSubject(curMethod, this::getObstacleAvoidanceTypeRx, 1000)
    }

    fun setObstacleAvoidanceBrakingDistanceRx(distance: Float): Completable {
        return Completable.create { emitter ->
            obstacleManager?.setObstacleAvoidanceBrakingDistance(distance) {
                SDKExtUtil.handleError(emitter, it)
            }
        }
    }

    fun getObstacleAvoidanceBrakingDistanceRx(): Single<Float> {
        return Single.create { emitter ->
            obstacleManager?.getObstacleAvoidanceBrakingDistance(CallbackWithRxHandler(emitter))
        }
    }

    fun getObstacleAvoidanceBrakingDistanceObservable(): Observable<Optional<Float>> {
        val curMethod = object : Any() {}.javaClass.enclosingMethod
        return autoGetProcessor.getAutoGetSubject(curMethod, this::getObstacleAvoidanceBrakingDistanceRx, 1000)
    }

    fun setObstacleAvoidanceEnableRx(enable: Boolean): Completable {
        return Completable.create { emitter ->
            obstacleManager?.setObstacleAvoidanceEnable(enable) {
                SDKExtUtil.handleError(emitter, it)
            }
        }
    }

    fun getObstacleAvoidanceEnableRx(): Single<Boolean> {
        return Single.create { emitter ->
            obstacleManager?.getObstacleAvoidanceEnable(CallbackWithRxHandler(emitter))
        }
    }

    fun getObstacleAvoidanceEnableObservable(): Observable<Optional<Boolean>> {
        val curMethod = object : Any() {}.javaClass.enclosingMethod
        return autoGetProcessor.getAutoGetSubject(curMethod, this::getObstacleAvoidanceEnableRx, 1000)
    }

    fun setObstacleCameraSourceRx(source: ObstacleCameraSource): Completable {
        return Completable.create { emitter ->
            obstacleManager?.setObstacleCameraSource(source) {
                SDKExtUtil.handleError(emitter, it)
            }
        }
    }

    fun getObstacleCameraSourceRx(): Single<ObstacleCameraSource> {
        return Single.create { emitter ->
            obstacleManager?.getObstacleCameraSource(CallbackWithRxHandler(emitter))
        }
    }


}